/*
 * $Id:
 *
 * Copyright (C) 2011 Refiner Inc.
 * All right reserved
 *
 *============================================================
 * +rVPN Stack : AppIF (Application Interface)
 *============================================================
 * abstract: This module provides rvs socket functions
 * author  : MURATA
 * history :
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "rvs_socket.h"
#include "rvs_msg.h"
#include "rvs_appif.h"

#include <net/if.h>

static int _rvs_close(int);
extern rvs_socks_t socks[];   /* defined in rvs_api_sock.c */
#ifndef _LINUX_TYPES_H
#include <linux/types.h>
#endif
#ifndef max
#define max(x, y) ({                          \
      typeof(x) _max1 = (x);                  \
      typeof(y) _max2 = (y);                  \
      (void) (&_max1 == &_max2);              \
      _max1 > _max2 ? _max1 : _max2; })
#endif
#ifndef min
#define min(x, y) ({                          \
      typeof(x) _min1 = (x);                  \
      typeof(y) _min2 = (y);                  \
      (void) (&_min1 == &_min2);              \
      _min1 < _min2 ? _min1 : _min2; })
#endif

#ifndef MAXTIMECHECK
#define MAXTIMECHECK 0
#endif

#ifndef TRACE_PACKET
#define TRACE_PACKET 0
#endif

#ifndef NO_THREADS
#define gettid    pthread_self
#endif

#define RVS_LOG_FILE	"/sdcard/refiner/rvpn/log/appif.log"

#if MAXTIMECHECK
/* 性能計測用 */
//#define MAXTIMECHECK    1024
static struct timeval chktv[MAXTIMECHECK];
static unsigned short chkln[MAXTIMECHECK];
static unsigned int chkpkt[MAXTIMECHECK];
static int ntm=0;

static void _trace_time(const char* msg,const char* buf,int len)
{
    if (buf==NULL) buf = "0000";

    /* 性能計測用 */
    if (ntm == MAXTIMECHECK) {
        int i;
        for (i=0; i<MAXTIMECHECK; i++) {
	  LOGD("%s[%04d]: %u.%06u %u %08X\n", msg,
               i,(unsigned int)chktv[i].tv_sec,(unsigned int)chktv[i].tv_usec,
                chkln[i], chkpkt[i]);
        }
        ntm=0;
    } else if (ntm < MAXTIMECHECK) {
        gettimeofday(&chktv[ntm], NULL);
        chkln[ntm] = len;
        chkpkt[ntm] = *(unsigned int*)buf;
        ntm++;
    }
}
#else /* MAXTIMECHECK */
#define _trace_time(a,b,c)  {}
#endif /* MAXTIMECHECK */

#if TRACE_PACKET
static void
trace_packet(const char* msg, const unsigned char* buff, int len, struct sockaddr_in* addr)
{
    char traceb[64], charb[32];
    int i;
    char *trp = traceb, *chp = charb;
    const unsigned char *src=buff;
    static FILE* logFp=NULL;
    struct timeval tv;

    if (logFp == NULL) {
        logFp = fopen(RVS_LOG_FILE, "a");
        if (logFp == NULL) return;
    }

    gettimeofday(&tv,NULL);
    strftime(traceb, 64, "%Y%m%d-%H%M%S", localtime(&tv.tv_sec));
    fprintf (logFp,"%s.%03d: === %s Trace Buffer\n",traceb,(int)tv.tv_usec/1000,msg);
    if (addr)
        fprintf (logFp,"       - Remote=%s:%d\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
    for (i=0; i<len; i++, src++) {
        sprintf (trp, "%02X ", *src); trp += 3;
        sprintf (chp, "%c", isprint(*src)?*src:'.'); chp++;
        if (((i+1)%16) == 0) {
            *trp = *chp = 0;
            fprintf (logFp, "%03x: %s %s\n",i-15,traceb, charb);
            trp = traceb; chp = charb;
        }
    }
    for (i%=16;i<16;i++) {
        sprintf (trp, "   "); trp += 3;
    }
    *trp = *chp = 0;
    fprintf (logFp, "%03X: %s %s\n",i-16, traceb, charb);
    fflush(logFp);
}
#else /* TRACE_PACKET */
#define trace_packet(a,b,c,d)	{}
#endif /* TRACE_PACKET */

#define	RVS_MAX_TIMEOUT	0x7FFFFFF

#define	RCVBUFLEN	256

typedef struct {
    char* ubuf;
    int   ubuflen;
} get_ubuf_t;

/* ユーザバッファ取得用関数 */
char* api_get_ubuf(int* length, void* param)
{
    get_ubuf_t* ubufp = (get_ubuf_t*)param;
    *length = ubufp->ubuflen;
    return ubufp->ubuf;
}

/* ソケットの生成 */
int rvs_socket(int domain, int type, int protocol)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int rsock = -1;
    int ksock = -1;;

    LOGD("(%d)%s: Enter(%d, %d, %d)\n", gettid(),  __FUNCTION__, domain, type, protocol);

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();

again:
    ksock=socket(domain, type, protocol);
    LOGD("%s: kernel socket() =  %d\n", __FUNCTION__, ksock);
    if ((ksock < 0)||(ksock >= MAX_FDS)){
        LOGE("%s: socket() failed.. sock=%d\n", __FUNCTION__, ksock);
        goto sockexit;
    }
    if(socks[ksock].sock_sts != 0){
        LOGE("%s: socks[%d].sock_sts = %d. should be 0.  try again.\n", __FUNCTION__, ksock, socks[ksock].sock_sts);
        goto again;
    }

    if(domain != AF_INET && domain != AF_INET6){
        socks[ksock].sock_sts = SOCK_NONVPN;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, ksock, socks[ksock].sock_sts);
        rsock = ksock;
        goto sockexit;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    //    this line was moved to earlier in this function.    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        socks[ksock].sock_sts = SOCK_NONVPN;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, ksock, socks[ksock].sock_sts);
        rsock = ksock;
        goto sockexit;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_SOCKET, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto sockerr;
    }

    /* パラメータの設定 */
    if (rvs_add_domain(smsg, domain) < 0) {
        goto sockerr;
    }
    if (rvs_add_type(smsg, type) < 0) {
        goto sockerr;
    }
    if (rvs_add_proto(smsg, protocol) < 0) {
        goto sockerr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_SOCKET\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        // 2012.02.10 koyama
        // ログアウト後に再度rvs_socketを呼ぶとrvs_api_new()でnsが
        // 取得できてしまうためここまで来てエラーになり、Exceptionが発生する。
        // goto sockerr;
        LOGE("%s: Error rvs_send_msg\n", __FUNCTION__);
        socks[ksock].sock_sts = SOCK_NONVPN;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, ksock, socks[ksock].sock_sts);
        rsock = ksock;
        rvs_api_free(ns);
        rvs_free(smsg);
        goto sockexit;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_SOCKET_RES, seqno,
                rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto sockerr;
    }

    /* 戻り値 */
    if(rmsg.header->status >= 0){
        socks[ksock].rvs_sock = rmsg.rsock->Integer;
        LOGD("%s: socks[%d].rvs_sock = %d\n", __FUNCTION__, ksock, socks[ksock].rvs_sock);
        socks[ksock].sock_sts = SOCK_CREATED;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, ksock, socks[ksock].sock_sts);
        rsock = ksock;
    }
    else {
      LOGD("%s: Request kernel close(%d)\n", __FUNCTION__, ksock);
      close(ksock);
      rsock = rmsg.header->status;
      if(rmsg.rerr)
	  rvs_set_errno(rmsg.rerr->Integer);
    }

sockerr:
    if(rsock < 0){
        LOGD("%s: Request kernel close(%d)\n", __FUNCTION__, ksock);
        close(ksock);
    }
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

sockexit:
    LOGD("%s: Return(%d).  fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, rsock, rsock, socks[rsock].sock_sts, socks[rsock].rvs_sock);
    return rsock;
}


/* ソケットのクローズ */
int rvs_close(int fd)
{
    int ret;

    LOGD("(%d)%s: Enter(%d), fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, fd, fd, socks[fd].sock_sts, socks[fd].rvs_sock);

    if(socks[fd].sock_sts == SOCK_NONE){
      ret=-1;
      LOGD("%s: Return(%d). already closed. \n", __FUNCTION__, ret);
      return ret;
    }

    if(socks[fd].rvs_sock != -1)
        _rvs_close(socks[fd].rvs_sock);
    socks[fd].rvs_sock = -1;
    socks[fd].sock_sts = SOCK_NONE;
    LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, fd, socks[fd].sock_sts);
    LOGD("%s: Rquest kernel close(%d)\n", __FUNCTION__, fd);
    ret = close(fd);
    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, fd, socks[fd].sock_sts, socks[fd].rvs_sock);
    return ret;
}

static int _rvs_close(int fd)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    LOGD("%s: Enter(%d)\n", __FUNCTION__, fd);

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_CLOSE, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto clserr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, fd) < 0) {
        goto clserr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
#ifdef SOCK_SPLIT_DBG
    LOGD("%s: Request RAPI_M_CLOSE\n", __FUNCTION__);
#endif

    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto clserr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_CLOSE_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto clserr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
    }

clserr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d).\n", __FUNCTION__, ret);
    return ret;
}

/* ソケットのBind */
int rvs_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;
    
    if (my_addr == NULL || addrlen == 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }
  
    LOGD("(%d)%s:%d Enter(%d, %s:%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, __LINE__, sockfd, inet_ntoa(((struct sockaddr_in *)my_addr)->sin_addr), ((struct sockaddr_in *)my_addr)->sin_port, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);

    if(socks[sockfd].sock_sts == SOCK_NONVPN){
        ret =  bind(sockfd, my_addr, addrlen);
        LOGD("%s:%d Request kernel bind()\n", __FUNCTION__, __LINE__);
        LOGD("%s:%d Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, __LINE__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;
    }
    if(socks[sockfd].sock_sts == SOCK_VPN){
        goto VPN;
    }
    if(my_addr -> sa_family == AF_INET && ((struct sockaddr_in *)my_addr) -> sin_addr.s_addr == htonl(INADDR_ANY)){
        LOGD("%s:%d AF_INET ANY\n", __FUNCTION__, __LINE__);
        goto VPN;
    } 
    if(my_addr -> sa_family == AF_INET6){
        __be32  *p = ((struct sockaddr_in6 *)my_addr)->sin6_addr.s6_addr32;
        if( p[0] | p[1] | p[2] | p[3]){
            LOGD("%s:%d AF_INET6 ANY\n",__FUNCTION__, __LINE__);
            goto VPN;
        }
    }
    if (rvs_get_vifroute(my_addr, NULL) < 0){
        LOGD("%s:%d rvs_get_vifroute returned negative\n", __FUNCTION__, __LINE__);
        socks[sockfd].sock_sts = SOCK_NONVPN;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, sockfd, socks[sockfd].sock_sts);

        ret = bind(sockfd, my_addr, addrlen);
        rvs_set_errno(errno);
        LOGD("%s:%d kernel bind() return (%d.%d)\n", __FUNCTION__, __LINE__, ret, errno);
        if(ret < 0)
            return ret;
        _rvs_close(socks[sockfd].rvs_sock);
        socks[sockfd].rvs_sock = -1;

        LOGD("%s:%d Return(%d).  fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, __LINE__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;      
    }

    socks[sockfd].sock_sts = SOCK_VPN;
    LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, sockfd, socks[sockfd].sock_sts);

VPN:
    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_BIND, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto binderr;
    }

    /* パラメータの設定 */
    if(rvs_add_rsock(smsg, socks[sockfd].rvs_sock) < 0 ){
        goto binderr;
    }
    if (rvs_add_addr(smsg, my_addr) < 0) {
        goto binderr;
    }
    
    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;
    
    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_BIND\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto binderr;
    }
    
    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_BIND_RES, seqno,
		      rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto binderr;
    }
    
    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
            LOGD("%s:%d RAPI_M_BIND rvs_errno=%d\n", __FUNCTION__, __LINE__, rvs_errno);
        }
    } else {
        ret = 0;
    }

binderr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d).  fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
    return ret;
}

  /* ソケットの接続 */
int rvs_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    if (serv_addr == NULL || addrlen == 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    LOGD("(%d)%s: Enter(%d, %s). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, sockfd, inet_ntoa(((struct sockaddr_in *)serv_addr)->sin_addr), sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);

    if(socks[sockfd].sock_sts == SOCK_NONVPN){
        ret =  connect(sockfd, serv_addr, addrlen);
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;
    }
    if( rvs_get_vifroute(NULL, serv_addr) < 0){
        socks[sockfd].sock_sts = SOCK_NONVPN;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, sockfd, socks[sockfd].sock_sts);
        _rvs_close(socks[sockfd].rvs_sock);
        socks[sockfd].rvs_sock = -1;
      
        LOGD("%s: Request kernel connect()\n", __FUNCTION__);
        ret = connect(sockfd, serv_addr, addrlen);
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;
    }
    socks[sockfd].sock_sts = SOCK_VPN;
    LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, sockfd, socks[sockfd].sock_sts);

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_CONNECT, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto connerr;
    }
    
    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[sockfd].rvs_sock) < 0){
        goto connerr;
    }
    if (rvs_add_addr(smsg, serv_addr) < 0) {
        goto connerr;
    }
    
    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;
  
    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_CONNECT\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto connerr;
    }
  
    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_CONNECT_RES, seqno,
                      rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto connerr;
    }
  
    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
    }
    
connerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    
    return ret;
}

/* 接続を待つ */
int rvs_listen(int sockfd, int backlog)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, sockfd, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);

    if(socks[sockfd].sock_sts == SOCK_NONVPN){

        LOGD("%s: Request kernel listen()\n", __FUNCTION__);
        ret = listen(sockfd, backlog);
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;
    }
    if(socks[sockfd].sock_sts != SOCK_VPN){
        ret = -1;
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__,  ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_LISTEN, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto liserr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[sockfd].rvs_sock) < 0) {
        goto liserr;
    }
    if (rvs_add_backlog(smsg, backlog) < 0) {
        goto liserr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_LISTEN\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto liserr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_LISTEN_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto liserr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
    }

liserr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

    return ret;
}

/* 接続を受ける */
int rvs_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;


    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, sockfd, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
    if(socks[sockfd].sock_sts == SOCK_NONVPN){
        LOGD("%s: Request kernel accept()\n", __FUNCTION__);
        if((ret =  accept(sockfd, addr, addrlen)) < 0)
            return ret;
        socks[ret].sock_sts = SOCK_NONVPN;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, ret, socks[ret].sock_sts);
        socks[ret].rvs_sock = -1;
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;
    }
    if(socks[sockfd].sock_sts != SOCK_VPN){
        ret = -1;
        LOGD("Fatal :%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
        return ret;
    }
    
    memset (&rmsg, 0, sizeof(rmsg));
    
    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }
    
    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_ACCEPT, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto rvfrerr;
    }
    
    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[sockfd].rvs_sock) < 0) {
        goto rvfrerr;
    }
    
    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;
    
    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_ACCEPT\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto rvfrerr;
    }
    
    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_ACCEPT_RES, seqno,
                      rcvbuf, RCVBUFLEN, NULL, 0) == NULL) {
        goto rvfrerr;
    }
    
    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = -1;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else if (rmsg.rsock) {
        if (addr && addrlen) {
            int len = rvs_get_addr (&rmsg, addr, *addrlen);
            if (len < 0) {
                ret = -1;
                goto rvfrerr;
            } else {
                ret = rmsg.rsock->Integer;
                *addrlen = len;
                {
                    int fd;
                    LOGD("%s: Request kernel socket()\n", __FUNCTION__);
                    if((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0){
                        socks[fd].sock_sts = SOCK_VPN;
                        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, fd, socks[fd].sock_sts);
                        socks[fd].rvs_sock = ret;
                        ret = fd;
                    }
                    else{
                        ret = -1;
                        LOGD("Fatal : %s: line#%d: socket failed\n", __FUNCTION__, __LINE__);
                    }
                }
            }
        }
    } else {
        ret = -1;
        rvs_set_errno(EIO);
    }
    
rvfrerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, sockfd, socks[sockfd].sock_sts, socks[sockfd].rvs_sock);
    return ret;
}
    
/* メッセージ送信 */
int rvs_sendto(int s, const void *buf, size_t len, int flags,
                      const struct sockaddr *to, socklen_t tolen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    if (buf == NULL || len == 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    if (to == NULL) {
        return rvs_send(s, buf, len, flags);
    }
    if (tolen == 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }
    LOGD("(%d)%s: Enter(%d, %s). fd=%d, sts=%d,  rvs_sock=%d\n",gettid(),  __FUNCTION__, s, inet_ntoa(((struct sockaddr_in *)to)->sin_addr), s, socks[s].sock_sts, socks[s].rvs_sock);

    trace_packet(__FUNCTION__, buf, len, (struct sockaddr_in*)to);

    if(socks[s].sock_sts == SOCK_NONE){
        return EBADF;
    }
    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: Request kernel sendto()\n", __FUNCTION__);
        ret =  sendto(s, buf, len, flags, to, tolen);
        LOGD("%s: Return(%d).\n", __FUNCTION__, ret);
        return ret;
    }
    if(socks[s].sock_sts == SOCK_CREATED){
        if(rvs_get_vifroute(NULL, to) < 0){
            socks[s].sock_sts = SOCK_NONVPN;
            LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, s, socks[s].sock_sts);
            _rvs_close(socks[s].rvs_sock);
            socks[s].rvs_sock = -1;
            LOGD("%s: Request kernel sendto()\n", __FUNCTION__);
            ret =  sendto(s, buf, len, flags, to, tolen);
            LOGD("%s: Return(%d).\n", __FUNCTION__, ret);
            return ret;
        }
        socks[s].sock_sts = SOCK_VPN;
        LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, s, socks[s].sock_sts);
    }
    
    memset (&rmsg, 0, sizeof(rmsg));
    
    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_SENDTO, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto sdtoerr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto sdtoerr;
    }
    if (rvs_add_addr(smsg, to) < 0) {
        goto sdtoerr;
    }
    if (rvs_add_flags(smsg, flags) < 0) {
        goto sdtoerr;
    }
    if (rvs_add_data(smsg, buf, len) < 0) {
        goto sdtoerr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    _trace_time(__FUNCTION__, (const char*)buf, len);

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_SENDTO\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto sdtoerr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_SENDTO_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto sdtoerr;
    }

    /* 戻り値 */
    ret = rmsg.header->status;
    if (rmsg.rerr) {
        rvs_set_errno(rmsg.rerr->Integer);
    }

sdtoerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

/* メッセージ受信 */
int rvs_recvfrom(int s, void *buf, size_t len, int flags,
                        struct sockaddr *from, socklen_t *fromlen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;
    get_ubuf_t ubuf = { buf, len };

//    LOGXX("##### %s Enter\n", __FUNCTION__);
    LOGD("%s:%d: Enter(%d)\n", __FUNCTION__, __LINE__);
    if (buf == NULL || len == 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }
    LOGD("%s:%d: from=%p\n", __FUNCTION__, __LINE__, from);

    if (from == NULL) {
        return rvs_recv(s, buf, len, flags);
    }
    if (fromlen == NULL) {
        rvs_set_errno(EINVAL);
        return -1;
    }
    LOGD("%s:%d: s=%d\n", __FUNCTION__, __LINE__, s);

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock);
    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: Request kernel recvfrom()\n", __FUNCTION__);
        ret = recvfrom(s, buf, len, flags, from, fromlen);
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }
    if(socks[s].sock_sts != SOCK_VPN){
        ret = -1;
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_RECVFROM, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto rvfrerr;
    }
    smsg->header.status = len;

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto rvfrerr;
    }
    if (rvs_add_flags(smsg, flags) < 0) {
        goto rvfrerr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_RECVFROM\n", __FUNCTION__);
//    LOGXX("##### %s >> rvs_send_msg\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto rvfrerr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_RECVFROM_RES, seqno,
                 rcvbuf, RCVBUFLEN, api_get_ubuf, &ubuf) == NULL) {
        goto rvfrerr;
    }
//    LOGXX("##### %s << rvs_recv_msg\n", __FUNCTION__);

    /* 戻り値 */
    ret = rmsg.header->status;
    if (rmsg.rerr) {
        rvs_set_errno(rmsg.rerr->Integer);
    }
    if (rmsg.data) {
        ret = rmsg.data->Length;
        if (ret > 0) {
            int len = rvs_get_addr (&rmsg, from, *fromlen);
            if (len < 0) {
                ret = -1;
                goto rvfrerr;
            } else {
                *fromlen = len;
            }
            trace_packet(__FUNCTION__, buf, ret, (struct sockaddr_in*)from);
        }
    }

rvfrerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

#ifdef SOCK_SPLIT_DBG
    LOGD("%s: Return(%d)\n", __FUNCTION__, ret);
#endif
//    LOGXX("##### %s Return\n", __FUNCTION__);
    return ret;
}

/* メッセージ送信 */
int rvs_send(int s, const void *buf, size_t len, int flags)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    if (buf == NULL || len == 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock);

    trace_packet(__FUNCTION__, buf, len, NULL);

    if(socks[s].sock_sts == SOCK_NONVPN){
    LOGD("%s: Request kernel send()\n", __FUNCTION__);
        ret = send(s, buf, len, flags);
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }
    if(socks[s].sock_sts != SOCK_VPN){
        ret = -1;
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_SEND, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto senderr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto senderr;
    }
    if (rvs_add_flags(smsg, flags) < 0) {
        goto senderr;
    }
    if (rvs_add_data(smsg, buf, len) < 0) {
        goto senderr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    _trace_time(__FUNCTION__, (const char*)buf, len);

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_SEND\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto senderr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_SEND_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto senderr;
    }

    /* 戻り値 */
    ret = rmsg.header->status;
    if (rmsg.rerr) {
        rvs_set_errno(rmsg.rerr->Integer);
    }

senderr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

/* メッセージ受信 */
int rvs_recv(int s, void *buf, size_t len, int flags)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;
    get_ubuf_t ubuf = { buf, len };

    if (buf == NULL || len == 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock);

    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: Request kernel recv()\n", __FUNCTION__);
        ret = recv(s, buf, len, flags);
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }
    if(socks[s].sock_sts != SOCK_VPN){
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_RECV, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto recverr;
    }
    smsg->header.status = len;

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto recverr;
    }
    if (rvs_add_flags(smsg, flags) < 0) {
        goto recverr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_RECV\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto recverr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_RECV_RES, seqno,
                 rcvbuf, RCVBUFLEN, api_get_ubuf, &ubuf) == NULL) {
        goto recverr;
    }

    /* 戻り値 */
    ret = rmsg.header->status;
    if (rmsg.rerr) {
        rvs_set_errno(rmsg.rerr->Integer);
    }
    if (rmsg.data) {
        ret = rmsg.data->Length;
        trace_packet(__FUNCTION__, buf, ret, NULL);
    }

recverr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

/* オプションの設定 */
int rvs_setsockopt(int s, int level, int optname,
                          const void *optval, socklen_t optlen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d, rvs_sock=%d\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock);

    if(socks[s].sock_sts == SOCK_NONE){
        ret = -1;
        LOGD("%s: line#%d: Return(%d). fd=%d, sts=%d\n", __FUNCTION__, __LINE__, ret, s, socks[s].sock_sts);
        return ret;
    }
    if(socks[s].sock_sts == SOCK_NONVPN || socks[s].sock_sts == SOCK_CREATED){
        ret = setsockopt(s, level, optname, optval, optlen);
        LOGD("%s: kernel setsockopt() return %d.\n", __FUNCTION__, ret);
    }
    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: Return(%d).\n", __FUNCTION__, ret); 
        return ret;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_SETSOCKOPT, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto ssoperr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto ssoperr;
    }
    if (rvs_add_level(smsg, level) < 0) {
        goto ssoperr;
    }
    if (rvs_add_opt(smsg, optname) < 0) {
        goto ssoperr;
    }
    if (optval) {
        if (rvs_add_value(smsg, optval, optlen) < 0) {
            goto ssoperr;
        }
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_SETSOCKOPT\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto ssoperr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_SETSOCKOPT_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto ssoperr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
    }

ssoperr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

/* オプションの取得 */
int rvs_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock);

    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: Request kernel getsockopt()\n", __FUNCTION__);
        ret =  getsockopt(s, level, optname, optval, optlen);
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }

    if(socks[s].sock_sts == SOCK_NONE){
        ret = -1;
        LOGD("%s: line#%d: Return(%d). fd=%d, sts=%d\n", __FUNCTION__, __LINE__, ret, s, socks[s].sock_sts);
        return ret;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_GETSOCKOPT, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto gsoperr;
    }
    smsg->header.status = *optlen;

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto gsoperr;
    }
    if (rvs_add_level(smsg, level) < 0) {
        goto gsoperr;
    }
    if (rvs_add_opt(smsg, optname) < 0) {
        goto gsoperr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_GETSOCKOPT\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto gsoperr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_GETSOCKOPT_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto gsoperr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
        if (optval) {
            if (rmsg.value) {
                if (*optlen > rmsg.value->Length) {
                    *optlen = rmsg.value->Length;
                }
                if (*optlen > 0) {
                    memcpy (optval, rmsg.value->String, *optlen);
                }
            } else {
                *optlen = 0;
            }
        }
    }

gsoperr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

/* ソケットの名前を取得 */
int rvs_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    if (name == NULL || namelen == NULL || *namelen <= 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock);

    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: Request kernel getsockname()\n", __FUNCTION__);
        ret = getsockname(s, name, namelen);
        LOGD("%s: Return(%d). ip=%s, fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, inet_ntoa(((struct sockaddr_in *)name)->sin_addr), s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }
    if(socks[s].sock_sts == SOCK_NONE){
        ret = -1;
        LOGD("%s:%d: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, __LINE__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_GETSOCKNAME, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto gsnmerr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto gsnmerr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_GETSOCKNAME\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto gsnmerr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_GETSOCKNAME_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto gsnmerr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        int len = rvs_get_addr (&rmsg, name, *namelen);
        if (len < 0) {
            ret = -1;
        } else {
            ret = 0;
            *namelen = len;
        }
    }

gsnmerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

    if(ret)
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    else
        LOGD("%s: Return(%d). ip=%s, fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, inet_ntoa(((struct sockaddr_in *)name)->sin_addr), s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

static struct _ioctl_func {
    int request;
    size_t arglen;
}   _rvs_iocreq[] = {
    { FIONBIO, sizeof(int) },
    { -1 }
};

/* ソケットデバイス制御 */
int rvs_ioctl(int s, int request, void *argp)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int req, ns, seqno;
    int ret = -1;
    int mode;

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d, rvs_sock=%d, request=%x\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock, request);

    if(socks[s].sock_sts == SOCK_NONE){
        LOGD("%s: Return(%d). fd=%d, sts=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts);
        return ret;
    }

    /* VPNモード設定 */
    if (request == VPNMODE) {
        LOGD("%s: request=VPNMODE\n", __FUNCTION__);
        mode = *((int *)argp);
        LOGD("%s: mode=%d\n", __FUNCTION__, mode);
        if (mode == MODE_USEVPN) {
            if(socks[s].sock_sts == SOCK_NONVPN) {
                LOGD("%s: Error sock_sts=SOCK_NONVPN\n", __FUNCTION__);
                return -1;
            }
            socks[s].sock_sts = SOCK_VPN;
            LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, s, socks[s].sock_sts);
        }
        else if (mode == MODE_NONVPN) {
            socks[s].sock_sts = SOCK_NONVPN;
            LOGD("%s:%d socks[%d].sock_sts = %d\n", __FUNCTION__, __LINE__, s, socks[s].sock_sts);
        }
        else {
            LOGD("%s: illegal mode\n", __FUNCTION__);
            return -1;
        }
        return 0;
    }

    if(socks[s].sock_sts == SOCK_NONVPN || socks[s].sock_sts == SOCK_CREATED){
        ret = ioctl(s, request, argp);
        LOGD("%s: Request kernel ioctl() return %d\n", __FUNCTION__, ret);
    }
    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: exit (0)\n", __FUNCTION__); 
        return 0;
    }

    for (req=0; _rvs_iocreq[req].request >= 0; req++) {
        if (_rvs_iocreq[req].request == request) {
            break;
        }
    }
    if (_rvs_iocreq[req].request < 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_IOCTL, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto iocerr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto iocerr;
    }
    if (rvs_add_request(smsg, request) < 0) {
        goto iocerr;
    }
    if (argp) {
        if (rvs_add_value(smsg, argp, _rvs_iocreq[req].arglen) < 0) {
            goto iocerr;
        }
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_IOCTL\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto iocerr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_IOCTL_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto iocerr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
        if (rmsg.value && argp) {
            if (_rvs_iocreq[req].arglen == rmsg.value->Length) {
                memcpy (argp, rmsg.value->String, rmsg.value->Length);
            }
        }
    }

iocerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

enum {
    FC_ARG_NONE,
    FC_ARG_LONG,
    FC_ARG_STRUCT
};

static struct _fcntl_func {
    int cmd;
    int type;
    size_t arglen;
}   _rvs_fccmd[] = {
    { F_GETFL, FC_ARG_NONE, 0 },
    { F_SETFL, FC_ARG_LONG, 0 },
    { -1 }
};

/* ソケットを操作する */
int rvs_fcntl(int fd, int cmd,...)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int req, ns, seqno;
    int ret = -1;
    va_list ap;
    long arg;
    void *argp = NULL;

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, fd, fd, socks[fd].sock_sts, socks[fd].rvs_sock);

    if(socks[fd].sock_sts == SOCK_NONE){
        LOGD("%s: Return(%d). fd=%d, sts=%d\n", __FUNCTION__, ret, fd, socks[fd].sock_sts);
        return ret;
    }
    if(socks[fd].sock_sts == SOCK_NONVPN){
        ret = fcntl(fd, cmd);
        LOGD("%s: Request kernel fcntl() return %d", __FUNCTION__, ret);
        return ret;
    }

    for (req=0; _rvs_fccmd[req].cmd >= 0; req++) {
        if (_rvs_fccmd[req].cmd == cmd) {
            break;
        }
    }
    if (_rvs_fccmd[req].cmd < 0) {
        rvs_set_errno(EINVAL);
        return -1;
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_FCNTL, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto fctlerr;
    }

    /* パラメータの設定 */
    if(rvs_add_rsock(smsg, socks[fd].rvs_sock) < 0) {
        goto fctlerr;
    }
    if (rvs_add_cmd(smsg, cmd) < 0) {
        goto fctlerr;
    }

    /* 付属データはcmdにより異なる */
    va_start(ap, cmd);
    switch (_rvs_fccmd[req].type) {
    case FC_ARG_NONE:
        break;
    case FC_ARG_LONG:
        arg = va_arg(ap, long);
        if (rvs_add_value (smsg, &arg, sizeof(long)) < 0) {
            goto fctlerr;
        }
        break;
    case FC_ARG_STRUCT:
        argp = va_arg(ap, void*);
        if (rvs_add_value (smsg, argp, _rvs_fccmd[req].arglen) < 0) {
            goto fctlerr;
        }
        break;
    }
    va_end(ap);

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_FCNTL\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto fctlerr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_FCNTL_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto fctlerr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
        if (argp && rmsg.value) {
            if (_rvs_fccmd[req].arglen == rmsg.value->Length) {
                memcpy (argp, rmsg.value->String, rmsg.value->Length);
            }
        }
    }

fctlerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__,  ret, fd, socks[fd].sock_sts, socks[fd].rvs_sock);

    return ret;
}

/* ソケットのI/O同期 */
/* standard */
/* transrate rVPN fds to kernel fds */
static int rvs_fd2fd(int rvs_fd)
{
    int i;
    for(i=0; i < MAX_FDS; i++){
        if(socks[i].rvs_sock == rvs_fd)
            return i;
    }
    LOGD("%s: faital. rvs_fd=%d doesn't exit\n", __FUNCTION__, rvs_fd);
    return -1;
}

int rvs_select(int nfds, fd_set *readfds, fd_set *writefds,
               fd_set *exceptfds, struct timeval *timeout)
{
    int ret = -1;
    fd_set nv_rfds, nv_wfds, nv_efds, v_rfds, v_wfds, v_efds;
    int    nv_nfds, v_nfds;
    int i;
    int i_max = min(FD_SETSIZE, nfds);

    if(timeout == NULL){
        LOGD("(%d)%s: Enter(nfds=%d, timeout=NULL).\n", gettid(), __FUNCTION__, nfds);
    }
    else{
        LOGD("(%d)%s: Enter(nfds=%d, timeout=%d.%d).\n", gettid(), __FUNCTION__, nfds, (int)timeout->tv_sec, (int)timeout->tv_usec);
    }

    FD_ZERO(&nv_rfds);
    FD_ZERO(&nv_wfds);
    FD_ZERO(&nv_efds);
    FD_ZERO(&v_rfds);
    FD_ZERO(&v_wfds);
    FD_ZERO(&v_efds);

    nv_nfds = v_nfds = 0;
        
    for(i=0; i < i_max; i++){
        if(readfds != NULL){
            if(FD_ISSET( i, readfds)){
                if(socks[i].sock_sts == SOCK_NONVPN){
                    FD_SET(i, &nv_rfds);
                    nv_nfds = i;
                }
                else {
                    FD_SET(i, &v_rfds);
                    v_nfds = i;
                }
            }
        }
        if(writefds != NULL){
            if(FD_ISSET(i, writefds)){
                if(socks[i].sock_sts == SOCK_NONVPN){
                    FD_SET(i, &nv_wfds);
                    nv_nfds = i;
                }
                else {
                    FD_SET(i, &v_wfds);
                    v_nfds = i;
                }
            }
        }
        if(exceptfds != NULL){
            if(FD_ISSET(i, exceptfds)){
                if(socks[i].sock_sts == SOCK_NONVPN){
                    FD_SET(i, &nv_efds);
                    nv_nfds = i;
                }
                else {
                    FD_SET(i, &v_efds);
                    v_nfds = i;
                }
            }
        }
    }
    if(v_nfds) ++v_nfds;
    if(nv_nfds) ++nv_nfds;
    ret = rvs_select_multi(v_nfds, &v_rfds, &v_wfds, &v_efds, nv_nfds, &nv_rfds, &nv_wfds, &nv_efds, timeout);
    for(i=0; i< v_nfds; i++) {
        if(FD_ISSET(i, &v_rfds))
            FD_SET(i, &nv_rfds);
        if(FD_ISSET(i, &v_wfds))
            FD_SET(i, &nv_wfds);
        if(FD_ISSET(i, &v_efds))
            FD_SET(i, &nv_efds);
    }
    if(readfds != NULL)
        bcopy(&nv_rfds, readfds, sizeof(fd_set));
    if(writefds != NULL)
        bcopy(&nv_wfds, writefds, sizeof(fd_set));
    if(exceptfds != NULL)
        bcopy(&nv_efds, exceptfds, sizeof(fd_set));

    LOGD("(%d)%s:  Return(%d).\n", gettid(), __FUNCTION__, ret);

    return ret;
}
/* _rvs_select() handles rVPN socket */
static int _rvs_select(int nfds, fd_set *readfds, fd_set *writefds,
                       fd_set *exceptfds, struct timeval *timeout)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;
    int tout;
    
    if(timeout == NULL){
        LOGD("%s: Enter(nfds=%d, timeout=NULL).\n", __FUNCTION__, nfds);
    }
    else{
        LOGD("%s: Enter(nfds=%d, timeout=%d.%d).\n", __FUNCTION__, nfds, (int)timeout->tv_sec, (int)timeout->tv_usec);
    }
      /* タイムアウトはRVS_MAX_TIMEOUTミリ秒以下 */
    if (timeout) {
        if (timeout->tv_sec > RVS_MAX_TIMEOUT/1000) {
            rvs_set_errno(EINVAL);
	    LOGE("%s: timeout.tv_sec(%d) > RVS_MAX_TIMEOUT/1000 \n", __FUNCTION__, (int)timeout->tv_sec);
            return -1;
        }
    }
    
    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_SELECT, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto selerr;
    }

    /* パラメータの設定 */
    if (timeout) {
        tout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
        if (rvs_add_tout(smsg, tout) < 0) {
            goto selerr;
        }
    }
    if (rvs_add_fdsets(smsg, nfds, readfds, writefds, exceptfds) < 0) {
        goto selerr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Requesting RAPI_M_SELECT\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        LOGE("%s: rvs_send_msg error[%d]\n", __FUNCTION__, rvs_errno);
        goto selerr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_SELECT_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        LOGE("%s: rvs_recv_msg error[%d]\n", __FUNCTION__, rvs_errno);
        goto selerr;
    }

    /* 戻り値 */
    ret = rmsg.header->status;
    if (ret < 0) {
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        rvs_get_fdsets (&rmsg, readfds, writefds, exceptfds);
    }

selerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

    LOGD("(%d)%s: Return(%d).\n ", gettid(), __FUNCTION__, ret);
    return ret;
 }

/* _rvs_select2() is identical to _rvs_select() but fds are got from rvs_socket() */
/* _rvs_select2() call _rvs_select() arter fds translation */

static int _rvs_select2(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
{
    int i, ret, rvnfds;
    fd_set rvreadfds, rvwritefds, rvexceptfds;
    fd_set rvreadfds2, rvwritefds2, rvexceptfds2;

    LOGD("%s: Enter(fds=%d)\n", __FUNCTION__, nfds);   

    FD_ZERO(&rvreadfds);
    FD_ZERO(&rvwritefds);
    FD_ZERO(&rvexceptfds);
   
    /* translation fds from rvs_sock() to  rVPN socket */ 
    rvnfds = 0;
    for(i=0; i < nfds; i++){
        if(readfds != NULL){
            if(FD_ISSET( i, readfds)){
                FD_SET(socks[i].rvs_sock, &rvreadfds);
                rvnfds = max(rvnfds, socks[i].rvs_sock);
            }
        }
        if(writefds != NULL){
            if(FD_ISSET(i, writefds)){
                FD_SET(socks[i].rvs_sock, &rvwritefds);
                rvnfds = max(rvnfds, socks[i].rvs_sock);
            }
        }
        if(exceptfds != NULL){
            if(FD_ISSET(i, exceptfds)){
                FD_SET(socks[i].rvs_sock, &rvexceptfds);
                rvnfds = max(rvnfds, socks[i].rvs_sock);
            }
        }
    }
    rvnfds++;

    ret = _rvs_select(rvnfds, &rvreadfds, &rvwritefds, &rvexceptfds, timeout);
    /* translation back from rVPN socket to rvs_socket()  */ 
    FD_ZERO(&rvreadfds2);
    FD_ZERO(&rvwritefds2);
    FD_ZERO(&rvexceptfds2);

    for(i=0; i< rvnfds; i++) {
        if(FD_ISSET(i, &rvreadfds))
            FD_SET(rvs_fd2fd(i), &rvreadfds2);
        if(FD_ISSET(i, &rvwritefds))
            FD_SET(rvs_fd2fd(i), &rvwritefds2);
        if(FD_ISSET(i, &rvexceptfds))
            FD_SET(rvs_fd2fd(i), &rvexceptfds2);
    }

    /* copy back resultant fds */
    if(readfds != NULL)
        bcopy(&rvreadfds2, readfds, sizeof(fd_set));
    if(writefds != NULL)
        bcopy(&rvwritefds2, writefds, sizeof(fd_set));
    if(exceptfds != NULL)
        bcopy(&rvexceptfds2, exceptfds, sizeof(fd_set));

    LOGD("%s: Return%d)\n", __FUNCTION__, ret);

   return ret;
 }

/* OSディスクリプタとの同期I/O */
int rvs_select_multi(int rvnfds, fd_set *rvreadfds,
           fd_set *rvwritefds, fd_set *rvexceptfds,
           int nfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;
    int tout;

    fd_set rvreadfds2, rvwritefds2, rvexceptfds2;
    int i, rvnfds2;

//    if(timeout == NULL){
//        LOGD("@@@@@ (%d)%s: Enter(rvnfds=%d, nfds=%d, timeout=NULL).\n",gettid(),  __FUNCTION__, rvnfds, nfds);
//    }
//    else{
//        LOGD("@@@@@ (%d)%s: Enter(rvnfds=%d, nfds=%d, timeout=%d.%d).\n",gettid(),  __FUNCTION__, rvnfds, nfds, (int)timeout->tv_sec, (int)timeout->tv_usec);
//    }

    /* どちらかのFDの指定がなければ単独のselect()をコールする */
    if (rvnfds == 0) {
        //LOGD("@@@@@ %s:%d: Request kernel select()\n", __FUNCTION__, __LINE__);
        ret = select(nfds, readfds, writefds, exceptfds, timeout);
        if(ret < 0) {
            rvs_set_errno(errno);
        }

//      if(ret < 0)
//          LOGD("@@@@@ (%d)%s:%d: Return(%d, %d).\n", gettid(), __FUNCTION__, __LINE__,  ret, errno);
//      else
//          LOGD("@@@@@ (%d)%s:%d: Return(%d).\n", gettid(), __FUNCTION__, __LINE__,  ret);
        return ret;
    }
    if (nfds == 0) {
        ret = _rvs_select2(rvnfds, rvreadfds, rvwritefds, rvexceptfds, timeout);
        //LOGD("@@@@@ (%d)%s:%d: Return(%d).\n", gettid(), __FUNCTION__, __LINE__, ret);
        return ret;
    }

    /* タイムアウトはRVS_MAX_TIMEOUTミリ秒以下 */
    if (timeout) {
        if (timeout->tv_sec > RVS_MAX_TIMEOUT/1000) {
            rvs_set_errno(EINVAL);
            //LOGD("@@@@@ (%d)%s:%d: Return(-1).\n", gettid(), __FUNCTION__, __LINE__);
            return -1;
        }
    }

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s:%d: cannot get spi_sock\n", __FUNCTION__, __LINE__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_SELECT, -1, 0);
    if (smsg == NULL) {
        LOGE("%s:%d: rvs_make_msg failed.\n", __FUNCTION__, __LINE__);
        goto selmerr;
    }

    /* パラメータの設定 */
    if (timeout) {
        tout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
        if (rvs_add_tout(smsg, tout) < 0) {
            //LOGD(@@@@@ "%s:%d: thru\n", __FUNCTION__, __LINE__);
            goto selmerr;
        }
    }

    rvnfds2 = 0;
    FD_ZERO(&rvreadfds2);
    FD_ZERO(&rvwritefds2);
    FD_ZERO(&rvexceptfds2);

    for(i=0; i < rvnfds; i++){
        if(rvreadfds != NULL){
            if(FD_ISSET( i, rvreadfds)){
                FD_SET(socks[i].rvs_sock, &rvreadfds2);
                rvnfds2 = max(rvnfds2, socks[i].rvs_sock);
                //LOGD("%s: readfds ksock=%d, rsock=%d\n", __FUNCTION__, i, socks[i].rvs_sock);
            }
        }
        if(rvwritefds != NULL){
            if(FD_ISSET(i, rvwritefds)){
                FD_SET(socks[i].rvs_sock, &rvwritefds2);
                rvnfds2 = max(rvnfds2, socks[i].rvs_sock);
                //LOGD("%s: writefds  ksock=%d, rsock=%d\n", __FUNCTION__, i, socks[i].rvs_sock);
            }
        }
        if(rvexceptfds != NULL){
            if(FD_ISSET(i, rvexceptfds)){
                FD_SET(socks[i].rvs_sock, &rvexceptfds2);
                rvnfds2 = max(rvnfds2, socks[i].rvs_sock);
                //LOGD("%s: exceptfds  ksock=%d, rsock=%d\n", __FUNCTION__, i, socks[i].rvs_sock);
            }
        }
    }
    rvnfds2++;
    if (rvs_add_fdsets(smsg, rvnfds2, &rvreadfds2, &rvwritefds2, &rvexceptfds2) < 0) {
        goto selmerr;
    }
    if (rvreadfds) FD_ZERO(rvreadfds);
    if (rvwritefds) FD_ZERO(rvwritefds);
    if (rvreadfds) FD_ZERO(rvreadfds);

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    //LOGD("@@@@@ %s:%d: Requesting RAPI_M_SELECT\n", __FUNCTION__, __LINE__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        //LOGD("@@@@@ %s:%d: thru\n", __FUNCTION__, __LINE__);
        goto selmerr;
    }

    /* OSのFDにAppIF用のソケットを追加 */
    FD_SET (rvs_api_sock(ns), readfds);
    if (nfds <= rvs_api_sock(ns)) {
        nfds = rvs_api_sock(ns) + 1;
    }

    /* OSの提供するselectの実行 */
    //LOGD("@@@@@ %s: Request kernel select(nfds=%d, timeout=%d.%d)\n", __FUNCTION__, nfds, (int)timeout->tv_sec, (int)timeout->tv_usec);
    ret = select (nfds, readfds, writefds, exceptfds, timeout);
    //LOGD("@@@@@ (%d)%s:%d: select() return(%d)\n",gettid(),  __FUNCTION__, __LINE__, ret);
    if (ret == 0) {
//        rvs_api_remove(ns);
//        goto selmexit;

        goto selmnext;
    }
    if (!FD_ISSET(rvs_api_sock(ns), readfds)) {
        //LOGD("@@@@@ %s:%d: thru\n", __FUNCTION__, __LINE__);
        rvs_api_remove(ns);
        goto selmexit;
    }
    ret--;
    FD_CLR(rvs_api_sock(ns), readfds);

selmnext:
    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_SELECT_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        //LOGD("@@@@@ %s:%d: thru\n", __FUNCTION__, __LINE__);
        goto selmerr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        //LOGD("@@@@@ %s:RAPI_M_SELECT returned status=%d\n", __FUNCTION__, ret);
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
	    //LOGD("%s:RAPI_M_SELECT errno=%d\n", __FUNCTION__, rvs_errno);
        }
    } else {
        //LOGD("@@@@@ %s:RAPI_M_SELECT returned status=%d\n", __FUNCTION__, ret);
        FD_ZERO(&rvreadfds2);
        FD_ZERO(&rvwritefds2);
        FD_ZERO(&rvexceptfds2);
        rvs_get_fdsets (&rmsg, &rvreadfds2, &rvwritefds2, &rvexceptfds2);
        ret += rmsg.header->status;
        for(i=0; i< rvnfds2; i++) {
            if(FD_ISSET(i, &rvreadfds2))
              FD_SET(rvs_fd2fd(i), rvreadfds);
            if(FD_ISSET(i, &rvwritefds2))
              FD_SET(rvs_fd2fd(i), rvwritefds);
            if(FD_ISSET(i, &rvexceptfds2))
              FD_SET(rvs_fd2fd(i), rvexceptfds);
        }
    }
    
selmerr:
    rvs_api_free(ns);
    
selmexit:
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    //LOGD("@@@@@ (%d)%s:%d: Return(%d)\n", gettid(), __FUNCTION__, __LINE__, ret);
    return ret;
}

/* ソケットの遮断 */
int rvs_shutdown(int s , int how )
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    LOGD("(%d)%s: Enter(%d). fd=%d, sts=%d,  rvs_sock=%d\n", gettid(), __FUNCTION__, s, s, socks[s].sock_sts, socks[s].rvs_sock);

    if(socks[s].sock_sts == SOCK_NONVPN){
        LOGD("%s: Request kernel shutdown()\n", __FUNCTION__);
        ret= shutdown(s, how);
        LOGD("%s:  Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }
    if(socks[s].sock_sts != SOCK_VPN){
        LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__, ret, s, socks[s].sock_sts, socks[s].rvs_sock);
        return ret;
    }
    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_SHUTDOWN, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto shdnerr;
    }

    /* パラメータの設定 */
    if (rvs_add_rsock(smsg, socks[s].rvs_sock) < 0) {
        goto shdnerr;
    }
    if (rvs_add_how(smsg, how) < 0) {
        goto shdnerr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    LOGD("%s: Request RAPI_M_SHUTDOWN\n", __FUNCTION__);
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto shdnerr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_SHUTDOWN_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, NULL) == NULL) {
        goto shdnerr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = rmsg.header->status;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = 0;
    }

shdnerr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);

    LOGD("%s: Return(%d). fd=%d, sts=%d,  rvs_sock=%d\n", __FUNCTION__,  ret, s, socks[s].sock_sts, socks[s].rvs_sock);
    return ret;
}

/* ローカルI/Fのアドレスを取得する */
int rvs_getlocalif(int type, struct sockaddr *addr, socklen_t *addrlen)
{
    rvs_api_send_t* smsg = NULL;
    rvs_api_msg_t rmsg;
    char rcvbuf[RCVBUFLEN];
    int ns, seqno;
    int ret = -1;

    /* 引数チェック */
    if ((addr == NULL) || addrlen == NULL || *addrlen == 0) {
        LOGE("%s: invalid params\n", __FUNCTION__);
        rvs_set_errno(EINVAL);
        return -1;
    }

    LOGD("(%d)%s: Enter\n", gettid(), __FUNCTION__);

    memset (&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if (ns < 0) {

#if 0 // 2012.02.10 koyama モバテク版では不要

     {
       struct ifreq ifr;
       int s, i;
       char *ifname[] = { "wlan0", "rmnet0"};      /* search wlan0 then rmnet0 and return its ip address */
       int err;

       if((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
	 return -1;
       for(i=0; i< 2; i++){
	 memset(&ifr, 0, sizeof(struct ifreq));
	 strncpy(ifr.ifr_name, ifname[i], strlen(ifname[i]));
	 if(ioctl(s, SIOCGIFADDR, &ifr) >= 0){
	   break;
	 }
	 err = errno;
       }
       close(s);
       if(i < 2){
	 LOGD("%s: Return(0). %s=%s\n", __FUNCTION__, ifname[i], inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
	 memcpy(addr, &ifr.ifr_addr, *addrlen);
	 return 0;
       }
       else{
	 LOGD("%s: Return(-1). ioctl(SIOCGIFADDR) failed(%d).\n", __FUNCTION__, err);
	 return -1;
       }
     }
#else 
       LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
#endif
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg(RAPI_M_GETLOCALIF, -1, 0);
    if (smsg == NULL) {
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto gtlierr;
    }

    /* パラメータの設定 */
    if (rvs_add_type(smsg, type) < 0) {
        goto gtlierr;
    }

    /* シーケンス番号の保存 */
    seqno = smsg->header.seqno;

    /* メッセージの送信 */
    if (rvs_send_msg (rvs_api_sock(ns), smsg) < 0) {
        goto gtlierr;
    }

    /* 応答の受信 */
    if (rvs_recv_msg (rvs_api_sock(ns), &rmsg, RAPI_M_GETLOCALIF_RES, seqno,
                 rcvbuf, RCVBUFLEN, NULL, 0) == NULL) {
        goto gtlierr;
    }

    /* 戻り値 */
    if (rmsg.header->status < 0) {
        ret = -1;
        if (rmsg.rerr) {
            rvs_set_errno(rmsg.rerr->Integer);
        }
    } else {
        ret = rmsg.header->status;
        if (addr && addrlen) {
            int len = rvs_get_addr (&rmsg, addr, *addrlen);
            if (len < 0) {
                ret = -1;
                goto gtlierr;
            } else {
                *addrlen = len;
            }
        }
    }

gtlierr:
    rvs_api_free(ns);
    if (smsg) {
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    if(ret == -1)
        LOGD("%s: Return(%d)\n", __FUNCTION__, ret);
    else
        LOGD("%s: Return(%d) %s\n", __FUNCTION__, ret, inet_ntoa(((struct sockaddr_in *)addr)->sin_addr));
    return ret;
}

/* 発信元と宛先のアドレスより対応する仮想インターフェースを取得する */
int rvs_get_vifroute( const struct sockaddr *addr, const struct sockaddr *daddr)
{
    rvs_api_send_t*  smsg = NULL;
    rvs_api_msg_t    rmsg;
    char  rcvbuf[RCVBUFLEN];
    int  ns, seqno;
    int  ret = -1;

    LOGD("%s: Enter\n", __FUNCTION__);
    memset(&rmsg, 0, sizeof(rmsg));

    /* 送信用ソケットの確保 */
    ns = rvs_api_new();
    if(ns < 0){
        LOGE("%s: cannot get spi_sock\n", __FUNCTION__);
        return -1;
    }

    /* 送信メッセージの作成 */
    smsg = rvs_make_msg( RAPI_M_GETVIFROUTE, -1, 0);
    if(smsg == NULL){
        LOGE("%s: rvs_make_msg failed.\n", __FUNCTION__);
        goto get_vifroute_err;
    }

    /* パラメータの設定 */
    if(addr)
        if(rvs_add_addr(smsg, addr) < 0)
            goto get_vifroute_err;

    if(daddr)
        if(rvs_add_daddr(smsg, daddr) < 0)
            goto get_vifroute_err;

    /* シーケンス番号の保存 */
    seqno = smsg -> header.seqno;

    /* メッセージの送信 */
    if(rvs_send_msg(rvs_api_sock(ns), smsg) < 0)
        goto get_vifroute_err;

    /* 応答の受信 */
    if(rvs_recv_msg(rvs_api_sock(ns), &rmsg, RAPI_M_GETVIFROUTE_RES, seqno, rcvbuf, RCVBUFLEN, NULL, NULL) == NULL)
        goto get_vifroute_err;

    /* 戻り値 */
    if(rmsg.header -> status < 0){
        ret = rmsg.header-> status;
        if(rmsg.rerr)
            rvs_set_errno(rmsg.rerr -> Integer);
    } else {
        ret = rmsg.vifno -> Integer;  /* インターフェス番号 */
    }

get_vifroute_err:
    rvs_api_free(ns);
    if(smsg){
        rvs_free(smsg);
    }
    rvs_free_msg(&rmsg);
    LOGD("%s: Return(%d.%d)\n", __FUNCTION__, ret, rvs_errno);
    return ret;
    // return 1;
}

